#ifndef H264_FRAMED_LIVE_SOURCE_HPP
#define H264_FRAMED_LIVE_SOURCE_HPP
#include "FramedSource.hh"
#include <glog/logging.h>
#include <opencv2/opencv.hpp>
#include "h264_encode.hpp"
#include <thread>
#include <mutex>
class VideoDevice;
class H264FramedLiveSource: public FramedSource
{
public:
    static H264FramedLiveSource* createNew(UsageEnvironment& env,VideoDevice* device);

    //redefined virtual functions
    virtual unsigned maxFrameSize() const;
protected:
    H264FramedLiveSource(UsageEnvironment& env,VideoDevice* device);
    virtual ~H264FramedLiveSource();
private:
    virtual void doGetNextFrame();
private:
    //此处添加自己需要的内容
    bool have_start_reading;
    VideoDevice* video_device_;
};

class VideoDevice
{
public:
    VideoDevice():capture_(0)
                 ,encoder_(1280,720,3000000,30)
                 ,h264_buffer_(nullptr)
    {
        h264_buffer_size_= 1280*720*3;
        h264_buffer_ = new uint8_t[h264_buffer_size_];
        enable_run_ = true;
        LOG(INFO)<<"Camera status:"<<capture_.isOpened();
        process_task_ = std::make_shared<std::thread>(std::bind(&VideoDevice::process_thread,this));
    }
    ~VideoDevice()
    {
        enable_run_=false;
        process_task_->join();
        capture_.release();
        delete[] h264_buffer_;
        
    }
    void get_h264_buffer(uint8_t* buffer,size_t* frame_size)
    {
        std::lock_guard<std::mutex> guard(lock_);
        memcpy(buffer,h264_buffer_,encoder_buffer_size_);
        *frame_size=encoder_buffer_size_;
    }
private:
    void process_thread()
    {
        while(enable_run_)
        {
            if(capture_.isOpened())
            {
                cv::Mat frame;
                if(capture_.read(frame))
                {
                    //LOG(INFO)<<"frame width:"<<frame.cols<<", height:"<<frame.rows;
                    //cv::imwrite("test.jpg",frame);
                    cv::cvtColor(frame,frame,CV_BGR2YUV_I420);
                    if(lock_.try_lock())
                    {
                        encoder_buffer_size_ = h264_buffer_size_;
                        encoder_.encode(frame.ptr(),h264_buffer_,&encoder_buffer_size_);
                        lock_.unlock();
                    }

                    //LOG(INFO)<<"encode finish, h264 buffer size:"<<encoder_buffer_size_;
                }
            }
            usleep(20000);
        }
    }
    cv::VideoCapture capture_;
    std::shared_ptr<std::thread> process_task_;
    std::atomic<bool> enable_run_;
    H264Encoder encoder_;
    uint8_t* h264_buffer_;
    size_t h264_buffer_size_;
    size_t encoder_buffer_size_;
    std::mutex lock_;
    
};
#endif